﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using BoYuanCore.Framework.MemoryCache;
using BoYuanCore.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Ubiety.Dns.Core;

namespace BoYuanCore.WebUI.Code.Filter
{
    /// <summary>
    /// 页面 事件，或button 权限许可
    /// </summary>
    public class AuthorizationFilterAttribute : ActionFilterAttribute, IAuthorizationFilter
    {
        //特性里注入接口方式 https://stackoverflow.com/questions/36109052/inject-service-into-action-filter/36109690
        private ICachingProvider _iCachingProvider;

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            _iCachingProvider = (ICachingProvider)context.HttpContext.RequestServices.GetService(typeof(ICachingProvider));//特性里注入接口方式

            //获取用户信息
            long userid = 0;
            ClaimsPrincipal principal = context.HttpContext.User;
            if (null != principal)
            {
                foreach (Claim claim in principal.Claims)
                {
                    //string str = "CLAIM TYPE: " + claim.Type + "; CLAIM VALUE: " + claim.Value + "</br>";
                    switch (claim.Type)
                    {
                        case "userid":
                            userid = Convert.ToInt64(claim.Value);
                            break;
                    }
                }
            }
            else
            {
                context.Result = new RedirectResult(UrlAddress.LoginUrl);//身份验证不通过，则跳转至此页面。
                return;
            }

            if (userid == 0)
            {
                context.Result = new RedirectResult(UrlAddress.LoginUrl);//用户id不正确，则跳转至此页面。
                return;
            }

            //通过请求动词判断 get为view，其他post等为button事件
            if (context.HttpContext.Request.Method.ToLower()!="get")
            {
                return;//非view 非页面级不进行权限验证判断
            }


            string controllerName = context.RouteData.Values["Controller"].ToString().ToLower();//通过ActionContext类的RouteData属性获取Controller的名称：Home
            string actionName = context.RouteData.Values["Action"].ToString().ToLower();//通过ActionContext类的RouteData属性获取Action的名称：Index
            string areaName = context.RouteData.Values["Area"]?.ToString().ToLower() + "";//通过ActionContext类的RouteData属性获取Area的名称：Admin
            string url = (areaName.Length>0? (areaName + "/"):string.Empty)+ controllerName + "/" + actionName;// home/index 或 admin/home/index

            //通过ActionContext类的ActionDescriptor属性，也可以获取Action的名称
            //不过这样获取到的是Action的完全限定名："AspNetCoreFilterContext.Controllers.HomeController.Index (AspNetCoreFilterContext)"，可以看到其中还包含Controller的类名、命名空间和程序集名称
            //string fullActionName = context.ActionDescriptor.DisplayName;

           
            //获取权限判断
            if (controllerName == "home")//排除公共页面
            {
                return;
            }

            var moduleAllList = DBServices.SysModule.GetSysModuleListByCache(_iCachingProvider, BaseController.HaveButtonPermissions);//获取所有的页面组件
            List<long> moduleIds = DBServices.SysModulePermissions.GetPermissionsByCache(userid, _iCachingProvider);//获取当前用户的对应角色的页面组件id集合
            bool havePermissions = false;

            //todo 非页面action判断(button权限，这个避免不了)
            if (moduleIds != null && moduleIds.Count > 0)
            {
                //context.HttpContext.Request.
                havePermissions = moduleAllList.Any(p => moduleIds.Contains(p.ID) && p.Url== url);
            }

            if (!havePermissions)
            {
                context.Result = new RedirectResult(UrlAddress.LoginUrl);//身份验证不通过，则跳转至此网站。
            }

            //context.HttpContext.Request.Form

        }

        //IActionFilter
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (BaseController.HaveButtonPermissions && filterContext.Controller is Controller controller)
            {
                //todo 权限判断输出js，用于隐藏button
                //controller.ViewBag.InitLoadJs = "alert('test_InitLoadJs');";
            }
        }
    }
}
/*
 权限说明：mvc方式页面加载，只能靠ViewBag传递状态值到view层，控制页面button显示权限。
 同通过权限AuthorizationFilterAttribute过滤器的OnAuthorization方法，获取请求url中的Area Controller Action对比数据库中的权限，无权限跳转到指定的页面。

 */
